<?php

namespace Tasker\Authorization;

use \Nette\Security\Permission;

class Authorizator extends Permission
{

	/**
	 * @var Acl
	 */
	protected $acl;
	/**
	 * @var TaskerModelsLocator
	 */
	protected $models;


	public function __construct(Acl $acl, \Tasker\Configurator\ModelsLocator $models)
	{
		$this->acl = $acl;
		$this->models = $models;

		foreach ($this->acl->getGlobalRoles() as $role)
		{
			$this->addRole($role['role']);
		}

		foreach ($this->acl->getGlobalResources() as $resource)
		{
			$this->addResource('user_' . $resource['resource']);
		}

		foreach ($this->acl->getGlobalRules() as $rule)
		{
			$this->allow($rule->user_role['role'], 'user_' . $rule->user_permission['resource'], $rule->user_permission['privilege']);
		}

		foreach ($this->acl->getProjectRoles() as $role)
		{
			$this->addRole($role['role']);
		}

		foreach ($this->acl->getProjectResources() as $resource)
		{
			$this->addResource('project_' . $resource['resource']);
		}

		foreach ($this->acl->getProjectRules() as $rule)
		{
			$this->allow($rule->project_role['role'], 'project_' . $rule->project_permission['resource'], $rule->project_permission['privilege']);
		}
	}

	public function isAllowed($role = self::ALL, $resource = self::ALL, $privilege = self::ALL)
	{
		if (strpos($role, 'user_') === 0 && parent::isAllowed($role, "user_" . $resource, $privilege))
		{
			return true;
		} elseif (strpos($role, 'user_') !== 0 && $resource instanceof ProjectResource)
		{
			return $this->isAllowedInProject($role, $resource, $privilege);
		} else
		{
			return false;
		}
	}

	public function isAllowedInProject($role = self::ALL, $resource = self::ALL, $privilege = self::ALL)
	{
		if (parent::isAllowed($role, "project_" . $resource, $privilege))
		{ // has role privilege for this type of resource? if yes - has current user in this role privilege for asked resource
			$projectId = $resource->id;
			$userId = $this->models->container->user->id;
			if (parent::isAllowed($role, "project_project", 'permission_inherit'))
			{
				$allowed = false;
				do
				{
					$allowed = $this->acl->hasRoleInProject($userId, $projectId, $role);
					if ($allowed == false)
						$projectId = $this->models->project->find($projectId)->getParentId();
				} while ($allowed == false && $projectId != null);
				return $allowed;
			}else
			{
				return $this->acl->hasRoleInProject($userId, $projectId, $role);
			}
		} else
		{
			return false;
		}
	}

}
